perm filename HELP.SAI[PNT,HE] blob
sn#598725 filedate 1981-07-07 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00008 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 ENTRY
C00003 00003 INTEGER #RECS,#LINKS,QUESTION_NODE,MENU_NODE,DISPLAY_NODE,PREVIOUS_DISPLAY_NODE
C00005 00004 PROCEDURE HELP_INIT
C00009 00005 PROCEDURE HELP_EXEC(INTEGER ARRAY INDEX,DATA STRING ARRAY KEYWORDS
C00019 00006 INTERNAL PROCEDURE HELP_END
C00020 00007 INTERNAL PROCEDURE HELP(STRING KEY(NULL))
C00021 00008 END
C00022 ENDMK
C⊗;
ENTRY;
BEGIN
DEFINE $$HELP=TRUE;
REQUIRE "HEADER.SAI" SOURCE_FILE;
COMMENT
This version makes use of the file HELP.RAN and accesses the
error messages randomly. It gives better performance than the previous
version that retrieved messages sequentially from HELP.DAT.
;
INTEGER #RECS,#LINKS,QUESTION_NODE,MENU_NODE,DISPLAY_NODE,PREVIOUS_DISPLAY_NODE;
INTEGER CURRENT_NODE;
INTEGER ARRAY NODE_STACK[1:10];
INTEGER STACKTOP; COMMENT CURRENT_NODE=NODE_STACK[STACKTOP];
INTEGER CHAN,BRCHAR,COUNT,EOF,FLAG,NCHAR;
STRING FNUM,FKEY,FRAN;
! break tables;
INTEGER CR_BREAK,PP_BREAK,BB_BREAK,IGNORECR_BREAK;
DEFINE $HEAD "<>"=<"******************** H E L P M O D E ********************************">;
DEFINE $TAIL "<>"=<"*************************************************************************">;
RCLASS IREC (INTEGER ARRAY I);
RCLASS SREC (STRING ARRAY S);
RPTR(IREC) $INDEX,$DATA,$RANACCS;
RPTR(SREC) $KEYWORDS;
STRING $HSTRING,$KSTRING,$BSTRING; ! help string,keyword stack;
INTEGER $LINE; ! top line being displayed;
BOOLEAN HELP_INITTED;
PROCEDURE HELP_INIT;
BEGIN "help_init" ! sets up the appropriate data arrays;
FNUM←"HELP.NUM[PNT,HE]";
FKEY←"HELP.KEY[PNT,HE]";
FRAN←"HELP.RAN[PNT,HE]";
OPEN(CHAN←GETCHAN,"DSK",'10,19,0,1000,BRCHAR,EOF);
LOOKUP(CHAN,FNUM,FLAG);
#RECS←WORDIN(CHAN);
#LINKS←WORDIN(CHAN);
QUESTION_NODE←WORDIN(CHAN);
MENU_NODE←WORDIN(CHAN);
BEGIN "read in and execute"
! data arrays ;
STRING ARRAY KEYWORDS[1:#RECS];
INTEGER ARRAY INDEX[1:#RECS];
INTEGER ARRAY DATA[1:#LINKS];
INTEGER ARRAY RANACCS[1:#RECS];
INTEGER I;
! load up the arrays;
ARRYIN(CHAN,INDEX[1],#RECS);
ARRYIN(CHAN,DATA[1],#LINKS);
ARRYIN(CHAN,RANACCS[1],#RECS);
RELEASE(CHAN);
! now get the keywords;
OPEN(CHAN←GETCHAN,"DSK",0,19,0,1000,BRCHAR,EOF);
LOOKUP(CHAN,FKEY,FLAG);
! initialize the break tables;
SETBREAK(PP_BREAK←GETBREAK,"%",NULL,"INS");
SETBREAK(CR_BREAK←GETBREAK,LF,CR,"INS");
SETBREAK(BB_BREAK←GETBREAK,"\",NULL,"INS");
SETBREAK(IGNORECR_BREAK←GETBREAK,NULL,LF,"INS");
INPUT(CHAN,PP_BREAK); ! get to beginning of data;
INPUT(CHAN,CR_BREAK); ! prime it first;
FOR I←1 STEP 1 UNTIL #RECS DO KEYWORDS[I]←INPUT(CHAN,CR_BREAK);
! get the keywords;
RELEASE(CHAN);
! prepare input file for HELP MESSAGES ;
OPEN(CHAN←GETCHAN,"DSK",0,19,0,NCHAR,BRCHAR,EOF);
LOOKUP(CHAN,FRAN,FLAG);
! put the data into records so as not to lose them ;
$INDEX←NEW_RECORD(IREC);
MEMORY[LOCATION(IREC:I[$INDEX])]↔MEMORY[LOCATION(INDEX)];
$RANACCS←NEW_RECORD(IREC);
MEMORY[LOCATION(IREC:I[$RANACCS])]↔MEMORY[LOCATION(RANACCS)];
$DATA←NEW_RECORD(IREC);
MEMORY[LOCATION(IREC:I[$DATA])]↔MEMORY[LOCATION(DATA)];
$KEYWORDS←NEW_RECORD(SREC);
MEMORY[LOCATION(SREC:S[$KEYWORDS])]↔MEMORY[LOCATION(KEYWORDS)];
END "read in and execute";
HELP_INITTED←TRUE;
DISPLAY_NODE←CURRENT_NODE←QUESTION_NODE;
STACKTOP←0;
END "help_init";
PROCEDURE HELP_EXEC(INTEGER ARRAY INDEX,DATA; STRING ARRAY KEYWORDS;
INTEGER ARRAY RANACCS);
BEGIN "help_exec"
! procedure returning the appropriate help message;
STRING PROCEDURE MESSAGES(INTEGER KEY);
BEGIN INTEGER MESSAGE_LENGTH,MESSAGE_START,MESSAGE_RECORD; STRING S;
MESSAGE_RECORD←(RANACCS[KEY] DIV 640)+1;
MESSAGE_START←RANACCS[KEY] MOD 640;
MESSAGE_LENGTH←RANACCS[KEY+1]-RANACCS[KEY];
USETI(CHAN,MESSAGE_RECORD);
NCHAR←MESSAGE_START; S←INPUT(CHAN,0); ! gets us to beginning of mess ;
NCHAR←MESSAGE_LENGTH; S←INPUT(CHAN,0); ! gets us the message ;
RETURN(S);
END;
STRING PROCEDURE NORMALIZE(STRING S);
BEGIN ! chops up long lines into lines with less 70-80 chars;
STRING S1,S2; INTEGER C;
IF LENGTH(S)≤80 THEN RETURN(S)
ELSE
S1←S[1 TO 70]; S2←S[71 TO ∞];
DO BEGIN
WHILE (C←LOP(S2))≠" " DO S1←S1&C;
S1←S1&CRLF&" "&S2[1 TO 60];
S2←S2[61 TO ∞];
END UNTIL EQU(S2,NULL);
RETURN(S1);
END;
SIMPLE INTEGER PROCEDURE ANCESTOR;
IF STACKTOP=1 THEN RETURN(CURRENT_NODE) ELSE
RETURN(NODE_STACK[STACKTOP-1]);
PROCEDURE DISPLAY(INTEGER NODE);
BEGIN "printing"
STRING HSTRING,KSTACK,BSTRING;INTEGER BR;INTEGER TPTR,LL,UL;
LL←INDEX[NODE]+1;UL←INDEX[NODE+1];
HSTRING←NULL;
FOR TPTR←LL STEP 1 UNTIL UL
DO HSTRING←HSTRING&CVTAB(KEYWORDS[DATA[TPTR]]
&TAB)&MESSAGES(DATA[TPTR])&CRLF;
KSTACK←"ANCESTORS:";
FOR TPTR←STACKTOP STEP -1 UNTIL 1 DO
KSTACK←KSTACK&TAB&KEYWORDS[NODE_STACK[TPTR]];
$KSTRING←CVTAB(KSTACK&CRLF);
$KSTRING←NORMALIZE($KSTRING);
$HSTRING←HSTRING&CRLF;
IF CURRENT_NODE≠QUESTION_NODE THEN
BEGIN
BSTRING←"BRETHREN:";
TPTR←ANCESTOR;
LL←INDEX[TPTR]+1;UL←INDEX[TPTR+1];
FOR TPTR←LL STEP 1 UNTIL UL DO
BSTRING←BSTRING&" "&KEYWORDS[DATA[TPTR]];
END ELSE BSTRING←NULL;
$BSTRING←CVTAB(BSTRING&CRLF);
$BSTRING←NORMALIZE($BSTRING);
SCROLL($HEAD,$HSTRING,$KSTRING&$BSTRING&$TAIL,"#### ");
PREVIOUS_DISPLAY_NODE←NODE;
END "printing";
INTEGER PROCEDURE CHECK_SUCCESSORS(STRING KEY; INTEGER NODE);
BEGIN
INTEGER I;
FOR I←INDEX[NODE]+1 STEP 1 UNTIL INDEX[NODE+1] DO
IF EQU(KEY,KEYWORDS[DATA[I]]) THEN RETURN(DATA[I]);
RETURN(0);
END;
INTEGER PROCEDURE CHECK_ANCESTORS(STRING KEY);
BEGIN
INTEGER I;
FOR I←STACKTOP STEP -1 UNTIL 1 DO
IF EQU(KEY,KEYWORDS[NODE_STACK[I]]) THEN RETURN(NODE_STACK[I]);
RETURN(0);
END;
PROCEDURE STACK(INTEGER NODE);
BEGIN
INTEGER I;
FOR I←STACKTOP STEP -1 UNTIL 1 DO
IF NODE=NODE_STACK[I] THEN BEGIN STACKTOP←I; RETURN END;
NODE_STACK[STACKTOP←STACKTOP+1]←NODE;
END;
PROCEDURE HELPER;
BEGIN STRING KEY; INTEGER BROTHER_NODE,ANCESTOR_NODE,SUCCESSOR_NODE;
DO BEGIN
STACK(CURRENT_NODE);
IF PREVIOUS_DISPLAY_NODE≠DISPLAY_NODE THEN DISPLAY (DISPLAY_NODE)
ELSE OUTSTR("#### ");
KEY←INCHWL;
IF EQU(KEY,"?") THEN DISPLAY_NODE←CURRENT_NODE←QUESTION_NODE
ELSE IF EQU(KEY,"MENU") THEN DISPLAY_NODE←CURRENT_NODE←MENU_NODE
ELSE IF EQU(KEY,"UP") THEN
DISPLAY_NODE←CURRENT_NODE←ANCESTOR
ELSE IF EQU(KEY,NULL) OR EQU(KEY,"DONE") THEN
DISPLAY_NODE←CURRENT_NODE
ELSE IF EQU(KEY,KEYWORDS[CURRENT_NODE]) THEN
DISPLAY_NODE←CURRENT_NODE
ELSE IF (SUCCESSOR_NODE←CHECK_SUCCESSORS(KEY,CURRENT_NODE)) THEN
DISPLAY_NODE←CURRENT_NODE←SUCCESSOR_NODE
ELSE IF (BROTHER_NODE←CHECK_SUCCESSORS(KEY,ANCESTOR))
THEN BEGIN DISPLAY_NODE←CURRENT_NODE←BROTHER_NODE;
STACKTOP←STACKTOP-1 END
ELSE IF (ANCESTOR_NODE←CHECK_ANCESTORS(KEY))
THEN DISPLAY_NODE←CURRENT_NODE←ANCESTOR_NODE
ELSE DISPLAY_NODE←QUESTION_NODE;
END UNTIL EQU(KEY,"DONE");
END;
PREVIOUS_DISPLAY_NODE←0; ! assume nothing displayed ;
HELPER;
END "help_exec";
INTERNAL PROCEDURE HELP_END;
IF HELP_INITTED THEN
BEGIN ! release the break tables;
INTEGER I;
FOR I←IGNORECR_BREAK,PP_BREAK,CR_BREAK,BB_BREAK DO RELBREAK(I);
RELEASE(CHAN); ! release the data file channel;
$INDEX←NULL_RECORD; $DATA←NULL_RECORD; $KEYWORDS←NULL_RECORD;$RANACCS←NULL_RECORD;
HELP_INITTED←FALSE;
END;
INTERNAL PROCEDURE HELP(STRING KEY(NULL));
BEGIN
IF NOT HELP_INITTED THEN HELP_INIT;
IF NOT EQU(KEY,NULL) THEN
BEGIN INTEGER I;
FOR I←#RECS STEP -1 UNTIL 1 DO IF EQU(KEY,SREC:S[$KEYWORDS][I])
THEN DONE;
IF I=0 THEN BEGIN PRINT("KEYWORD "&KEY&" IS UNKNOWN"&CRLF);
DISPLAY_NODE←CURRENT_NODE←QUESTION_NODE;
END
ELSE BEGIN DISPLAY_NODE←CURRENT_NODE←I; STACKTOP←0; END;
END;
HELP_EXEC(IREC:I[$INDEX],IREC:I[$DATA],SREC:S[$KEYWORDS],
IREC:I[$RANACCS]);
$SCROLLED←FALSE;
END;
END;